using System;
using CthulhuDomain.StageManagement;
using Microsoft.Xna.Framework;
using CthulhuDomain.GameEntities;

namespace CthulhuDomain.Services
{
  public class ScoreManager
  {
    private static volatile ScoreManager instance;

    private static readonly object syncRoot = new Object();

    public static ScoreManager Instance {
      get {
        if (instance == null) {
          lock (syncRoot) {
            if (instance != null) return instance;
            instance = new ScoreManager();
          }
        }

        return instance;
      }
    }

    public static IRectangle Context { get; set; }
    public static IGraphicResource Font { get; set; }
    protected static IColor DrawingColor { get; set; }

    private static string Text {
      get { return string.Format("{0}", Score); }
    }

    public static long Score { get; set; }
    internal static int Hearts { get; set; }
    protected static IGraphicResource HeartTexture { get; set; }
    protected static IGraphicResource BackGroundTexture { get; set; }
    protected static IContentManager ContentManager { get; set; }
    protected static ISpriteBatch SpriteBatch { get; set; }
    protected static IGameServiceProvider GameServiceManager { get; set; }

    public static void LoadContent() {
      Font = ContentManager.LoadFont("Impact");
      BackGroundTexture = ContentManager.LoadTexture("px");
      HeartTexture = ContentManager.LoadTexture("heart");
    }

    public static StateManagerResult Update(DomainEntityMatrix army, DomainEntity player) {
      var collisionResult = CollisionManager.DetectCollision(army, player);
      
      Score += collisionResult.Amount;
      Hearts = player.LifePoint;
      var stateResult = new StateManagerResult {LifePoints = Hearts, Score = Score};

      switch (collisionResult.ResultType) {
        case CollisionResult.eResultType.IncreaseScore:
          stateResult.Result |= eStateManagerResult.Continue;
          if (Convert.ToBoolean(collisionResult.ResultType & CollisionResult.eResultType.PowerUp))
          {
            stateResult.Result |= eStateManagerResult.PowerUp;
            stateResult.ResultText = collisionResult.ResultText;
            collisionResult.Modifier.Execute(ref player,ref army);
          }
            
          break;
        case CollisionResult.eResultType.StageComplete:
          stateResult.Result |= eStateManagerResult.NewLevel;
          
          break;
        case CollisionResult.eResultType.PlayerDie:
          stateResult.Result |= eStateManagerResult.GameOver;
          Reset();
          break;

        default:
          if (collisionResult.Modifier != null)
          {
            collisionResult.Modifier.Execute(ref player, ref army);
            stateResult.ResultText = collisionResult.ResultText;
          }

          break;
      }
      return stateResult;
    }

    public static void Draw() {
      if (SpriteBatch == null) return;
      var background = new DrawableRectangle(BackGroundTexture, new Vector2Adapter(0, 0),
                                             new RectangleAdapter(0, 0, Context.Width, 25),
                                             new ColorAdapter(Color.Yellow));

      var heart = new DrawableContent(HeartTexture, new Vector2Adapter(0, 0),
                                      new RectangleAdapter(0, 0, 19, 15),
                                      new ColorAdapter(Color.White));

      SpriteBatch.Draw(background.Texture, background.Position, background.DestinationRectangle, background.Color);

      var p = new Vector2Adapter(5, 5);

      for (var i = 0; i < Hearts; i++) {
        SpriteBatch.Draw(heart.Texture, p, heart.Rectangle, heart.Color, new Vector2Adapter((float)1, (float)1), 1);
        p.X += 20;
      }

      SpriteBatch.DrawString(Font, string.Format("Score:{0}", Text),
                             new Vector2Adapter(Context.Width - (Text.Length * 10 + 70), 0), DrawingColor);
    }

    public static void Initialize(IGameServiceProvider gameServiceProvider) {
      GameServiceManager = gameServiceProvider;
      Context = new RectangleAdapter(GameServiceManager.Context.X, GameServiceManager.Context.Y,
                                     GameServiceManager.Context.Width, GameServiceManager.Context.Height);
      DrawingColor = new ColorAdapter(Color.Black);
      ContentManager = GameServiceManager.ContentManager;
      SpriteBatch = GameServiceManager.SpriteBatch;
    }

    public static void Reset() {
      Score = 0;
    }

    #region Nested type: CollisionResult

    public class CollisionResult
    {
      #region eResultType enum

      [Flags]
      public enum eResultType
      {
        None = 0,
        IncreaseScore = 1 << 0,
        PlayerDie = 1 << 1,
        StageComplete = 1 << 2,
        PowerUp = 1 << 3
      }

      #endregion

      public eResultType ResultType { get; set; }
      public int Amount { get; set; }

      public IPowerImplementator Modifier { get; set; }

      public string ResultText { get; set; }

      public void IncreaseScore(int amount) {
        ResultType |= eResultType.IncreaseScore;
        Amount = amount;
      }
    }

    #endregion
  }

  public class StateManagerResult
  {
    public StateManagerResult(eStateManagerResult result, int lifePoints) {
      Result = result;
      LifePoints = lifePoints;
      Score = 0;
    }

    public StateManagerResult(eStateManagerResult result, int lifePoints, long score) {
      Result = result;
      LifePoints = lifePoints;
      Score = score;
    }

    public StateManagerResult() {
    }

    public long Score { get; set; }
    public eStateManagerResult Result { get; set; }
    public int LifePoints { get; set; }

    public string ResultText { get; set; }
  }

  public class DrawableContent
  {
    public DrawableContent(IGraphicResource graphicResource, IVector2 vector2, IRectangle rectangle, IColor color) {
      Texture = graphicResource;
      Position = vector2;
      Rectangle = rectangle;
      Color = color;
    }

    public IGraphicResource Texture { get; set; }
    public IVector2 Position { get; set; }
    public IRectangle Rectangle { get; set; }
    public IColor Color { get; set; }
  }
}